//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This is a sample for BCGControlBar Library Professional Edition
// Copyright (C) 1998-2016 BCGSoft Ltd.
// All rights reserved.
//
// This source code can be used, distributed or modified
// only under terms and conditions 
// of the accompanying license agreement.
//*******************************************************************************
//
// ChartVirtualView.cpp : implementation file
//

#include "stdafx.h"
#include "bcgpchartexample.h"
#include "ChartVirtualView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CChartVirtualView

IMPLEMENT_DYNCREATE(CChartVirtualView, CBCGPChartExampleView)

CChartVirtualView::CChartVirtualView()
	: CBCGPChartExampleView(CChartVirtualView::IDD)
{
	//{{AFX_DATA_INIT(CChartVirtualView)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}

CChartVirtualView::~CChartVirtualView()
{
}

void CChartVirtualView::DoDataExchange(CDataExchange* pDX)
{
	CBCGPChartExampleView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CChartVirtualView)
	DDX_Control(pDX, IDC_CHART, m_wndChart);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CChartVirtualView, CBCGPChartExampleView)
	//{{AFX_MSG_MAP(CChartVirtualView)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CChartVirtualView diagnostics

#ifdef _DEBUG
void CChartVirtualView::AssertValid() const
{
	CBCGPChartExampleView::AssertValid();
}

void CChartVirtualView::Dump(CDumpContext& dc) const
{
	CBCGPChartExampleView::Dump(dc);
}
#endif //_DEBUG

class CVirtualSeries : public CBCGPChartAreaSeries
{
public:
	CVirtualSeries(CBCGPChartVisualObject* pChart) : CBCGPChartAreaSeries(pChart)
	{

	}

	/// Sample data creation
	void CreateData(int nDataPointCount)
	{
		m_arXValues.SetSize(nDataPointCount);
		m_arYValues.SetSize(nDataPointCount);
		m_arScreenPoints.SetSize(nDataPointCount);

		COleDateTime dtCurrTime = COleDateTime::GetCurrentTime();
		COleDateTime dtStart(dtCurrTime.GetYear(), 1, 1, 0, 0, 0);
		COleDateTimeSpan dtInterval(1, 0, 0, 0);

		double dblVal = 0;
		for (int i = 0; i < nDataPointCount; i++)
		{
			double dblDelta = dblVal > 100 ? Rand(-100, 100) : Rand(0, 200);
			dblVal += dblDelta;

			m_arXValues[i] = dtStart.m_dt;
			m_arYValues[i] = dblVal;

			dtStart += dtInterval;
		}
	}

	COleDateTime GetFirstDate() const
	{
		return m_arXValues[0];
	}

	COleDateTime GetLastDate() const
	{
		return m_arXValues[m_arXValues.GetSize() - 1];
	}

	/// Data point management - called by Chart
	virtual int GetDataPointCount() const
	{
		return (int)m_arXValues.GetSize();
	}

	virtual const CBCGPChartDataPoint* GetDataPointAt(int nIndex) const
	{
		// m_virtualPoint is defined in CBCGPChartSeries and can be used to return wrapped data,
		// but it has to be unconsted
		CBCGPChartDataPoint* pDP = (CBCGPChartDataPoint*)&m_virtualPoint;

		pDP->SetComponentValue(m_arYValues[nIndex]);
		pDP->SetComponentValue(m_arXValues[nIndex], CBCGPChartData::CI_X);

		return &m_virtualPoint;
	}

	virtual CBCGPChartValue GetDataPointValue(int nDataPointIndex, CBCGPChartData::ComponentIndex ci) const
	{
		if (ci == CBCGPChartData::CI_Y)
		{
			return m_arYValues[nDataPointIndex];
		}

		if (ci == CBCGPChartData::CI_X)
		{
			return m_arXValues[nDataPointIndex];
		}

		return CBCGPChartValue();
	}
	/// End Data point 

	/// Screen position management - called by Chart
	/// nScreenPointIndex is usually required for stacked charts
	virtual void SetDataPointScreenPoint(int nDataPointIndex, int /*nScreenPointIndex*/, CBCGPPoint pt)
	{
		m_arScreenPoints[nDataPointIndex] = pt;
	}

	virtual CBCGPPoint GetDataPointScreenPoint(int nDataPointIndex, int /*nScreenPointIndex*/) const
	{
		return m_arScreenPoints[nDataPointIndex];
	}

	virtual BOOL IsDataPointScreenPointsEmpty(int nDataPointIndex) const 
	{
		return (m_arScreenPoints.GetSize() == 0 || nDataPointIndex >= m_arScreenPoints.GetSize());
	}
	/// End screen position management

protected:
	CArray<double, double>	m_arYValues;
	CArray<double, double>	m_arXValues;
	CBCGPPointsArray		m_arScreenPoints;
};

/////////////////////////////////////////////////////////////////////////////
// CChartVirtualView message handlers

void CChartVirtualView::OnInitialUpdate() 
{
	CBCGPChartExampleView::OnInitialUpdate();
	
	if (m_bIsReady)
	{
		return;
	}

	m_bIsReady = TRUE;

	CBCGPChartVisualObject* pChart = m_wndChart.GetChart();
	ASSERT_VALID(pChart);

	pChart->SetLegendPosition(BCGPChartLayout::LP_NONE);
	
	CVirtualSeries* pVirtualSeries = new CVirtualSeries(pChart);
	pVirtualSeries->CreateData(365);
	pVirtualSeries->SetCurveType(BCGPChartFormatSeries::CCT_SPLINE);
	
	pChart->AddSeries(pVirtualSeries);
	pChart->RecalcMinMaxValues();
	
	CBCGPChartAxis* pXAxis = pChart->GetChartAxis(BCGP_CHART_X_PRIMARY_AXIS);
	pXAxis->m_bFormatAsDate = TRUE;
	pXAxis->UseApproximation(FALSE);
	pXAxis->SetFixedDisplayRange(pVirtualSeries->GetFirstDate(), pVirtualSeries->GetLastDate());
	pXAxis->m_axisLabelsFormat.m_textFormat.SetDrawingAngle(90);

	SetDefaultLineWidth();
}
